package com.easymin.weixin;

import com.easymin.weixin.entity.WeixinXmlEntity;
import com.easymin.weixin.mapper.WxBindMapper;
import com.easymin.weixin.service.impl.WeixinQrCodeServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhyu
 * @date
 */
public class WeixinServlet extends HttpServlet {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");

    private String getDateStr() {
        return sdf.format(new Date());
    }

    private WxBindMapper wxBindMapper;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");
        System.out.println(getDateStr() + " doGet==========================" + getIpAddress(req));
        System.out.printf("signature = %s , timestamp= %s , nonce=%s ,echostr = %s", signature, timestamp, nonce, echostr);
        String[] values = {"scezu08313056676", timestamp, nonce};
        Arrays.sort(values); // 字典序排序
        String value = values[0] + values[1] + values[2];
        String sign = DigestUtils.shaHex(value);
        PrintWriter writer = resp.getWriter();
        if (signature.equals(sign)) {// 验证成功返回ehcostr
            writer.print(echostr);
        } else {
            writer.print("error");
        }
        System.out.println("doGet");
        writer.flush();
        writer.close();
    }


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(getDateStr() + "doPost==========================" + getIpAddress(request));
        ServletInputStream inputStream = request.getInputStream();
        String s = "";
        if (null == wxBindMapper)
            initMapper(request);
        response.setContentType("application/xml");
        response.setCharacterEncoding("UTF-8");
        try {
            System.out.println("try parse Xml ==========================");
            BufferedReader rf = new BufferedReader(new InputStreamReader(inputStream));
            String str = null;
            StringBuilder sb = new StringBuilder();
            while (null != (str = rf.readLine())) {
                sb.append(str);
            }
            System.out.println(sb.toString());
            WeixinXmlEntity entity = WeixinXmlEntity.parseStreamToEntity(sb.toString());
            if (null != entity.getEncrypt()) {
                //解密逻辑 或者在parse Entity时的时候解密
            }
            System.out.println("get entity = " + entity);
            if (entity.getMsgtype().equals("event") && null != entity.getEvent()) {
                //收到了事件
                switch (entity.getEvent()) {
                    //更改 关注后不做任何处理
                    case WeixinXmlEntity.SCAN:
                        s = deal_defaultEvent(entity);
                        break;
                    case WeixinXmlEntity.SUBSCRIBE:
                        s = deal_defaultEvent(entity);
                        break;
                    case WeixinXmlEntity.UNSUBSCRIBE:
                        break;
                }
            } else if (entity.getMsgtype().equals("text")) {
                //收到了文本消息
                s = deal_defaultText(entity);
            }


        } catch (Exception e) {
            System.out.println("parse xml faild");
            e.printStackTrace();
        }
        PrintWriter out = response.getWriter();
        inputStream.close();
        inputStream = null;
        out.println(s);
        out.close();
        System.out.println("response = " + s);
        out = null;
    }

    /***
     * 默认文本处理
     * @param entity
     * @return
     */
    public String deal_defaultText(WeixinXmlEntity entity) {
        return sendTextToWeixinPeopleNumberUser(entity,CONTENT_TO_PEOPEL_NUMBER_USER_TEXT);
    }

    /***
     * 默认事件处理
     * @param entity
     * @return
     */
    private String deal_defaultEvent(WeixinXmlEntity entity) {
        String s = "";
        if (null != entity.getTicket()) {//扫码必有ticket
            System.out.println("发现ticket, 用户是应该是由扫码进入公众号!");
            String eventkey = entity.getEventkey();
            if (null != eventkey) {
                String data = eventkey.replace("qrscene_", "");
                String driverId = null;
                String name = null;
                String type = null;
                if (null != data) {
                    String[] datas = data.split(WeixinQrCodeServiceImpl.SEPARATE);
                    if (null != datas && datas.length >= 3) {
                        type = datas[0];
                        name = datas[2];
                        driverId = datas[1];
                    }
                }
                if (null != type && null != driverId)
                    s = sendBindDriverMessage(entity, driverId, name);
            }
        }
        return s;
    }

    /***
     * 接收发送交换后发送
     * @return
     */
    public String sendTextToWeixinPeopleNumberUser(WeixinXmlEntity entity, String context) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("ToUserName",entity.getFromusername());
        map.put("FromUserName",entity.getTousername());
        map.put("CreateTime",String.valueOf(System.currentTimeMillis()));
        map.put("Content", context);
        return mapToXml(TEMP_TEXT, map);
    }



    /***
     * 发送接收 交换送
     * @param entity
     * @param driverId
     * @param name
     * @return
     */
    private String sendBindDriverMessage(WeixinXmlEntity entity, String driverId, String name) {
        String s = null;
        Map<String, String> map = new HashMap<String, String>();
//        Long count = wxBindMapper.findOpenIdExist(entity.getFromusername());
//        if (0 != count) {
        //已注册
//            map.put("ToUserName", entity.getFromusername());
//            map.put("FromUserName", entity.getTousername());
//            long time = System.currentTimeMillis();
//            map.put("CreateTime", String.valueOf(time));
////            map.put("title1", "你早已注册为公众号用户");
//            map.put("description1", "你早已注册为公众号用户,[e族出行] 往后余生，竭诚为你服务");
//            map.put("picurl", "https://www.scezu.com/assets/img/ezu.png");
//            s = mapToXml(TEXT, map);
//            System.out.println("事件:" + entity.getEvent() + " ;openid[" + entity.getFromusername() + "已注册,仅发送文档");
//        } else {
        //没注册
        if (null != driverId) {
            map.put("ToUserName", entity.getFromusername());
            map.put("FromUserName", entity.getTousername());
            long time = System.currentTimeMillis();
            map.put("CreateTime", String.valueOf(time));
            map.put("title1", "驾驶员\"" + name + "\"邀请你注册，单单有红包");
            map.put("description1", "[e族出行] 往后余生，竭诚为你服务");
            map.put("picurl", "https://www.scezu.com/assets/img/ezu.png");
            map.put("url", "https://wx.scezu.com/v5/da21e0b8e1924c6c8e91726d9e8ca74b?appId=wx1355564bc57135ed&code=0815RGHp0bovZn1A0ZGp0GJgHp05RGHh&driverId=" + driverId);
        }
        s = mapToXml(TEMP, map);
        System.out.println("事件:" + entity.getEvent() + " ;openid[" + entity.getFromusername() + "没注册,发送红包信息,和推荐driverId");

//        }
        return s;
    }

    public static String mapToXml(String temp, Map<String, String> map) {
        String re = new String(temp);
        for (String item : map.keySet()) {
            re = re.replace("#{" + item + "}", map.get(item));
        }
        return re;
    }

    public static String mapToXml(Map<String, String> map) {
        String xml = "<xml>";
        for (String item : map.keySet()) {
            xml += "<" + item + ">";
            xml += map.get(item);
            xml += "</" + item + ">";
        }
        xml += "</xml>";
        return xml;
    }

    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * <p>
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     * <p>
     * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
     * 192.168.1.100
     * <p>
     * 用户真实IP为： 192.168.1.110
     *
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public Object getObject(Class z, HttpServletRequest request) {
        ServletContext servletContext = request.getServletContext();
        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        return webApplicationContext.getBean(z);
    }

    public void initMapper(HttpServletRequest req) {
        wxBindMapper = (WxBindMapper) getObject(WxBindMapper.class, req);
    }

    /***
     * 回复普通文本回话模板
     */
    public static final String TEMP_TEXT = "<xml>\n" +
            "  <ToUserName><![CDATA[#{ToUserName}]]></ToUserName>\n" +
            "  <FromUserName><![CDATA[#{FromUserName}]]></FromUserName>\n" +
            "  <CreateTime>#{CreateTime}</CreateTime>\n" +
            "  <MsgType><![CDATA[text]]></MsgType>\n" +
            "  <Content><![CDATA[#{Content}]]></Content>\n" +
            "</xml>";

    /**
     * 图文链接模板
     */
    public static final String TEMP = "<xml>\n" +
            "  <ToUserName><![CDATA[#{ToUserName}]]></ToUserName>\n" +
            "  <FromUserName><![CDATA[#{FromUserName}]]></FromUserName>\n" +
            "  <CreateTime>#{CreateTime}</CreateTime>\n" +
            "  <MsgType><![CDATA[news]]></MsgType>\n" +
            "  <ArticleCount>1</ArticleCount>\n" +
            "  <Articles>\n" +
            "    <item>\n" +
            "      <Title><![CDATA[#{title1}]]></Title>\n" +
            "      <Description><![CDATA[#{description1}]]></Description>\n" +
            "      <PicUrl><![CDATA[#{picurl}]]></PicUrl>\n" +
            "      <Url><![CDATA[#{url}]]></Url>\n" +
            "    </item>\n" +
            "  </Articles>\n" +
            "</xml>";

    /***
     * 简单文字描述模板
     */
    public static final String TEXT = "<xml>\n" +
            "  <ToUserName><![CDATA[#{ToUserName}]]></ToUserName>\n" +
            "  <FromUserName><![CDATA[#{FromUserName}]]></FromUserName>\n" +
            "  <CreateTime>#{CreateTime}</CreateTime>\n" +
            "  <MsgType><![CDATA[text]]></MsgType>\n" +
            "  <Content><![CDATA[#{description1}]]></Content>\n" +
            "</xml>";

    public static final String TEMP_WITHOUT_URL = "<xml>\n" +
            "  <ToUserName><![CDATA[#{ToUserName}]]></ToUserName>\n" +
            "  <FromUserName><![CDATA[#{FromUserName}]]></FromUserName>\n" +
            "  <CreateTime>#{CreateTime}</CreateTime>\n" +
            "  <MsgType><![CDATA[news]]></MsgType>\n" +
            "  <ArticleCount>1</ArticleCount>\n" +
            "  <Articles>\n" +
            "    <item>\n" +
            "      <Title><![CDATA[#{title1}]]></Title>\n" +
            "      <Description><![CDATA[#{description1}]]></Description>\n" +
            "      <PicUrl><![CDATA[#{picurl}]]></PicUrl>\n" +
            "    </item>\n" +
            "  </Articles>\n" +
            "</xml>";
    public static final String CONTENT_TO_PEOPEL_NUMBER_USER_TEXT = "感谢您使用“e族出行”，您有任何出行需要及建议欢迎随时致电预约热线400-0831-800";

}
